package com.happy3w.cmds.refactor;

import com.beust.jcommander.Parameter;
import com.happy3w.bean.factory.DecodeHelper;
import com.happy3w.cmds.command.ArgAppCmd;
import com.happy3w.cmds.command.NoneSplitter;
import com.happy3w.cmds.maven.GraphOption;
import com.happy3w.cmds.maven.mermaid.MermaidDrawer;
import com.happy3w.cmds.maven.model.JavaModule;
import com.happy3w.cmds.maven.model.JavaModuleDictionary;
import com.happy3w.cmds.maven.model.ModuleFile;
import com.happy3w.cmds.refactor.config.ChangePackageConfig;
import com.happy3w.cmds.refactor.config.ChangePackageConfigVo;
import com.happy3w.cmds.refactor.config.ChangePackageItemConfig;
import com.happy3w.cmds.refactor.config.ModulePackageConfig;
import com.happy3w.cmds.utils.JsonUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

@Component
public class ChangePackageCmd extends ArgAppCmd<ChangePackageCmd.Args> {

    @Override
    public String getName() {
        return "change-package";
    }

    @Getter
    @Setter
    public static class Args {
        @Parameter(names = {"-p", "--projects"}, description = "root project dirs", required = true, splitter = NoneSplitter.class)
        private List<String> projectDirs = new ArrayList<>();

        @Parameter(names = {"-c", "--config"}, description = "change package config file")
        private String changePackageConfig;

        @Parameter(names = {"-d", "--dry-run"}, description = "just dry run")
        private boolean dryRun;

        @Parameter(names = {"-o", "--output"}, description = "output file")
        private String outputFile;
    }

    public ChangePackageCmd() {
        super(ChangePackageCmd.Args.class);
    }

    @Override
    public void runWithArg(Args args) throws Exception {
        List<JavaModule> parentModules = args.projectDirs.stream()
                .map(JavaModule::extract)
                .toList();
        JavaModuleDictionary dictionary = JavaModuleDictionary.from(parentModules);

        ChangePackageConfigVo configVo = JsonUtils.instance.loadFromFile(new File(args.changePackageConfig), ChangePackageConfigVo.class);
        ChangePackageConfig config = ChangePackageConfig.from(configVo);
        dictionary.streamAllModules().forEach(module -> {
            System.out.println("Processing " + module.takeKey());
            ModulePackageConfig moduleConfig = config.getModuleConfig(module.takeKey());
            try (Stream<ModuleFile> files = module.allFiles()) {
                files.map(ModuleFile::toClassInfo)
                        .filter(Objects::nonNull)
                        .forEach(classInfo -> {
                            String newClassName = moduleConfig.changePackage(classInfo.fullClassName());
                            if (newClassName == null || Objects.equals(classInfo.fullClassName(), newClassName)) {
                                return;
                            }
                            System.out.println(classInfo.fullClassName() + " -> " + newClassName);
                });
            }
        });
    }

}
